from random import choice
import tkinter as tk
from tkinter import messagebox


def ButtonState(state):
    button0.config(state=state)
    button1.config(state=state)
    button2.config(state=state)
    button3.config(state=state)
    button4.config(state=state)
    button5.config(state=state)
    button6.config(state=state)
    button7.config(state=state)
    button8.config(state=state)


def check():
    global player
    board = [
        block0.get(),
        block1.get(),
        block2.get(),
        block3.get(),
        block4.get(),
        block5.get(),
        block6.get(),
        block7.get(),
        block8.get()
    ]
    if '' not in board:
        messagebox.showinfo('游戏结束', '该局平局')
        ButtonState('disabled')
    else:
        a = None
        detail = ''
        # 判定行
        for i in range(3):
            if board[i * 3] == board[i * 3 + 1] == board[i * 3 + 2] != '':
                a = True
                detail = board[i * 3]
        # 判定列
        for i in range(3):
            if board[i] == board[i + 3] == board[i + 6] != '':
                a = True
                detail = board[i]
        # 判定对角线
        if board[0] == board[4] == board[8] != '' or board[2] == board[
                4] == board[6] != '':
            a = True
            detail = board[4]
        if a is True:
            messagebox.showinfo('游戏结束', '{}玩家胜利'.format(detail))
            ButtonState('disabled')
            status.set('游戏结束')
        else:
            status.set('现在是{}玩家'.format('O' if player % 2 == 0 else 'X'))
        print(a, detail, player)
        if player % 2 == 1:
            think(board)
            player += 1
            check()


def think(sta):
    result = -1
    for i in range(3):
        if sta[i * 3] == sta[i * 3 + 1] == 'X' and sta[i * 3 + 2] == '':
            result = i * 3 + 2
    for i in range(3):
        if sta[i * 3] == sta[i * 3 + 2] == 'X' and sta[i * 3 + 1] == '':
            result = i * 3 + 1

    for i in range(3):
        if sta[i * 3 + 1] == sta[i * 3 + 2] == 'X' and sta[i * 3] == '':
            result = i * 3

    for i in range(3):
        if sta[i] == sta[i + 3] == 'X' and sta[i + 6] == '':
            result = i + 6

    for i in range(3):
        if sta[i] == sta[i + 6] == 'X' and sta[i + 3] == '':
            result = i + 3

    for i in range(3):
        if sta[i + 3] == sta[i + 6] == 'X' and sta[i] == '':
            result = i

    if sta[0] == sta[4] == 'X' and sta[8] == '':
        result = 8
    if sta[0] == sta[8] == 'X' and sta[4] == '':
        result = 4
    if sta[4] == sta[8] == 'X' and sta[0] == '':
        result = 0
    if sta[2] == sta[4] == 'X' and sta[6] == '':
        result = 6
    if sta[0] == sta[6] == 'X' and sta[4] == '':
        result = 4
    if sta[4] == sta[6] == 'X' and sta[2] == '':
        result = 2

    for i in range(3):
        if sta[i * 3] == sta[i * 3 + 1] == 'O' and sta[i * 3 + 2] == '':
            result = i * 3 + 2

    for i in range(3):
        if sta[i * 3] == sta[i * 3 + 2] == 'O' and sta[i * 3 + 1] == '':
            result = i * 3 + 1

    for i in range(3):
        if sta[i * 3 + 1] == sta[i * 3 + 2] == 'O' and sta[i * 3] == '':
            result = i * 3

    for i in range(3):
        if sta[i] == sta[i + 3] == 'O' and sta[i + 6] == '':
            result = i + 6

    for i in range(3):
        if sta[i] == sta[i + 6] == 'O' and sta[i + 3] == '':
            result = i + 3

    for i in range(3):
        if sta[i + 3] == sta[i + 6] == 'O' and sta[i] == '':
            result = i

    if sta[0] == sta[4] == 'O' and sta[8] == '':
        result = 8
    if sta[0] == sta[8] == 'O' and sta[4] == '':
        result = 4
    if sta[4] == sta[8] == 'O' and sta[0] == '':
        result = 0
    if sta[2] == sta[4] == 'O' and sta[6] == '':
        result = 6
    if sta[0] == sta[6] == 'O' and sta[4] == '':
        result = 4
    if sta[4] == sta[6] == 'O' and sta[2] == '':
        result = 2

    if result == -1:
        if sta == ['' for i in range(9)]:
            result = 4
        else:
            empty_positions = [i for i, x in enumerate(sta) if x == '']
            if empty_positions:
                result = choice(empty_positions)
    if result == 0:
        block0.set('X')
    elif result == 1:
        block1.set('X')
    elif result == 2:
        block2.set('X')
    elif result == 3:
        block3.set('X')
    elif result == 4:
        block4.set('X')
    elif result == 5:
        block5.set('X')
    elif result == 6:
        block6.set('X')
    elif result == 7:
        block7.set('X')
    elif result == 8:
        block8.set('X')


def fill(where):
    global player
    board = [
        block0.get(),
        block1.get(),
        block2.get(),
        block3.get(),
        block4.get(),
        block5.get(),
        block6.get(),
        block7.get(),
        block8.get()
    ]
    if board[where] != '':
        messagebox.showinfo('!!!', '这个格子已经被填了……')
    else:
        if player % 2 == 0:
            if where == 0:
                block0.set('O')
            elif where == 1:
                block1.set('O')
            elif where == 2:
                block2.set('O')
            elif where == 3:
                block3.set('O')
            elif where == 4:
                block4.set('O')
            elif where == 5:
                block5.set('O')
            elif where == 6:
                block6.set('O')
            elif where == 7:
                block7.set('O')
            elif where == 8:
                block8.set('O')
            player += 1
        check()


def again():
    global player
    if messagebox.askyesno('谁先手', '你希望你先下棋子吗') is True:
        player = 0
    else:
        player = 1
    ButtonState('normal')
    block0.set('')
    block1.set('')
    block2.set('')
    block3.set('')
    block4.set('')
    block5.set('')
    block6.set('')
    block7.set('')
    block8.set('')
    status.set('现在是{}的回合'.format('你(O)' if player % 2 == 0 else '机器人(X)'))
    if player % 2 == 1:
        board = [
            block0.get(),
            block1.get(),
            block2.get(),
            block3.get(),
            block4.get(),
            block5.get(),
            block6.get(),
            block7.get(),
            block8.get()
        ]
        think(board)
        player += 1
    status.set('现在是{}的回合'.format('你(O)' if player % 2 == 0 else '机器人(X)'))


if __name__ == '__main__':
    root = tk.Tk()
    root.geometry('300x330+100+100')
    root.title('Tic-Tac-Toe (人机版)')
    # 变量
    player = -1
    status = tk.StringVar()
    status.set('现在是{}的回合'.format('你(O)' if player % 2 == 0 else '机器人(X)'))
    block0 = tk.StringVar()
    block1 = tk.StringVar()
    block2 = tk.StringVar()
    block3 = tk.StringVar()
    block4 = tk.StringVar()
    block5 = tk.StringVar()
    block6 = tk.StringVar()
    block7 = tk.StringVar()
    block8 = tk.StringVar()
    # 一层控件
    tk.Label(root, text='井字棋', font=('楷体', 20)).pack(padx=4, pady=2)
    frame = tk.Frame(root)
    frame.pack(padx=4, pady=2)
    btn_again = tk.Button(root, text='重新开始', font=('楷体', 20), command=again)
    btn_again.pack(padx=4, pady=2)
    tk.Label(root, textvariable=status, font=('楷体', 15)).pack(padx=4, pady=2)
    # 二层控件
    button0 = tk.Button(frame,
                        textvariable=block0,
                        font=("Montserrat", 20, "bold"),
                        height=1,
                        width=3,
                        command=lambda: fill(0))
    button0.grid(row=0, column=0, padx=4, pady=2)
    button1 = tk.Button(frame,
                        textvariable=block1,
                        font=("Montserrat", 20, "bold"),
                        height=1,
                        width=3,
                        command=lambda: fill(1))
    button1.grid(row=0, column=1, padx=4, pady=2)
    button2 = tk.Button(frame,
                        textvariable=block2,
                        font=("Montserrat", 20, "bold"),
                        height=1,
                        width=3,
                        command=lambda: fill(2))
    button2.grid(row=0, column=2, padx=4, pady=2)
    button3 = tk.Button(frame,
                        textvariable=block3,
                        font=("Montserrat", 20, "bold"),
                        height=1,
                        width=3,
                        command=lambda: fill(3))
    button3.grid(row=1, column=0, padx=4, pady=2)
    button4 = tk.Button(frame,
                        textvariable=block4,
                        font=("Montserrat", 20, "bold"),
                        height=1,
                        width=3,
                        command=lambda: fill(4))
    button4.grid(row=1, column=1, padx=4, pady=2)
    button5 = tk.Button(frame,
                        textvariable=block5,
                        font=("Montserrat", 20, "bold"),
                        height=1,
                        width=3,
                        command=lambda: fill(5))
    button5.grid(row=1, column=2, padx=4, pady=2)
    button6 = tk.Button(frame,
                        textvariable=block6,
                        font=("Montserrat", 20, "bold"),
                        height=1,
                        width=3,
                        command=lambda: fill(6))
    button6.grid(row=2, column=0, padx=4, pady=2)
    button7 = tk.Button(frame,
                        textvariable=block7,
                        font=("Montserrat", 20, "bold"),
                        height=1,
                        width=3,
                        command=lambda: fill(7))
    button7.grid(row=2, column=1, padx=4, pady=2)
    button8 = tk.Button(frame,
                        textvariable=block8,
                        font=("Montserrat", 20, "bold"),
                        height=1,
                        width=3,
                        command=lambda: fill(8))
    button8.grid(row=2, column=2, padx=4, pady=2)
    again()
    root.mainloop()
